﻿using log4net;
using McsUtility;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MinerManager
{
	public partial class FrmMain : Form
	{
		ILog logger = LogManager.GetLogger(typeof(Program));
		private Common.AgentComponent Agent = new Common.AgentComponent();

		private Forms.UserLogin FormLogin = null;//用户登录窗体
		private Forms.Reconnect FormReconnect = null;//掉线重连窗体

		private ContextMenuStrip RightContextMenu = null;//右键菜单

		private int TotalCount = 0;//数据总量
		private int PageIndex = 1;//页码
		private int PageSize = 20;//显示数量
		private int PageCount = 1;//总页码

		private bool AllowRefreshHashrate = false;//是否允许刷新算力。
		private bool AllowTimerRefreshHashrate = true;//是否允许Timer执行刷新算力信息

		public FrmMain()
		{
			InitializeComponent();
			MinerList.DoubleBufferedListView(true);
		}

		#region 窗体事件

		private void FrmMain_Load(object sender, EventArgs e)
		{
			this.Text = Common.Utility.SoftName;
			BottomStatus_Version.Text = Common.Utility.SoftName + " " + Common.Utility.Version;
			SetControlStatus(false);
			Init();
			InitAgent();
			LoadContextMenu();

			//自动登录
			if (System.IO.File.Exists(Common.Utility.AutoLoginPath))
			{
				string autoLoginString = System.IO.File.ReadAllText(Common.Utility.AutoLoginPath, Encoding.UTF8);
				if (!string.IsNullOrWhiteSpace(autoLoginString))
				{
					//连接服务器
					Common.ConnectionServer conn = new Common.ConnectionServer(this.Agent);
					conn.Connection();

					//发送数据
					if (this.Agent.IsStarted)
					{
						Common.Data.LoginUserName = autoLoginString.Split(',')[0];
						Common.Data.LoginPassWord = autoLoginString.Split(',')[1];

						McsUtility.Models.LoginModel info = new McsUtility.Models.LoginModel
						{
							LoginName = Common.Data.LoginUserName,
							LoginPass = Common.Data.LoginPassWord
						};
						byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.LoginModel>(ProtoType.MinerManagerLogin, info);
						this.Agent.AgentSend(bytes);
					}
					else
					{
						MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
						ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
					}
				}
			}
		}

		private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (this.Agent.IsStarted)
			{
				this.Agent.OnShutdown -= new EventHandler<EventArgs>(Agent_OnShutdown);
				this.Agent.Stop();
			}
		}

		private void LoadContextMenu()
		{
			this.RightContextMenu = new ContextMenuStrip();

			#region 矿机信息

			Action<object, EventArgs> hashrateClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					ListView.SelectedListViewItemCollection items = MinerList.SelectedItems;
					if (items.Count > 0)
					{
						McsUtility.Models.MinersModel info = items[0].Tag as McsUtility.Models.MinersModel;

						Action<object, EventArgs> onClose = delegate (object closeObj, EventArgs closeArgs)
						{
							this.AllowRefreshHashrate = true;
						};

						this.AllowRefreshHashrate = false;
						Forms.MinerHashrate form = new Forms.MinerHashrate(this.Agent, info.ID, info.MinerName, info.FirstCoin, info.SecondCoin);
						form.OnClose += new EventHandler<EventArgs>(onClose);
						form.ShowDialog();
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemHashrate = new ToolStripMenuItem("矿机信息");
			itemHashrate.Click += new EventHandler(hashrateClick);
			this.RightContextMenu.Items.Add(itemHashrate);

			#endregion

			#region 矿机日志

			Action<object, EventArgs> minerLogClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					ListView.SelectedListViewItemCollection items = MinerList.SelectedItems;
					if (items.Count > 0)
					{
						McsUtility.Models.MinersModel info = items[0].Tag as McsUtility.Models.MinersModel;

						Forms.MinerLog form = new Forms.MinerLog(this.Agent, info.ID, info.MinerName);
						form.ShowDialog();
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemMinerLog = new ToolStripMenuItem("矿机日志");
			itemMinerLog.Click += new EventHandler(minerLogClick);
			this.RightContextMenu.Items.Add(itemMinerLog);

			#endregion

			#region 开始挖矿事件

			Action<object, EventArgs> startClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					if (MessageBox.Show("确定要开始挖矿吗？", "开始挖矿", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
					{
						ListView.SelectedListViewItemCollection items = MinerList.SelectedItems;
						if (items.Count > 0)
						{
							McsUtility.Models.MinersModel info = items[0].Tag as McsUtility.Models.MinersModel;

							byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerStartMining, new int[] { info.ID });
							this.Agent.AgentSend(bytes);
							MessageBox.Show("开始挖矿指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
						}
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemStart = new ToolStripMenuItem("开始挖矿");
			itemStart.Click += new EventHandler(startClick);
			this.RightContextMenu.Items.Add(itemStart);

			#endregion

			#region 停止挖矿事件

			Action<object, EventArgs> stopClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					if (MessageBox.Show("确定要停止挖矿吗？", "停止挖矿", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
					{
						ListView.SelectedListViewItemCollection items = MinerList.SelectedItems;
						if (items.Count > 0)
						{
							McsUtility.Models.MinersModel info = items[0].Tag as McsUtility.Models.MinersModel;

							byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerEndMining, new int[] { info.ID });
							this.Agent.AgentSend(bytes);
							MessageBox.Show("停止挖矿指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
						}
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemStop = new ToolStripMenuItem("停止挖矿");
			itemStop.Click += new EventHandler(stopClick);
			this.RightContextMenu.Items.Add(itemStop);

			#endregion

			#region 重启矿机事件

			Action<object, EventArgs> restartClick = delegate (object obj, EventArgs args)
			{
				if (MessageBox.Show("确定要重启矿机吗？", "重启矿机", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					if (this.Agent.IsStarted)
					{
						ListView.SelectedListViewItemCollection items = MinerList.SelectedItems;
						if (items.Count > 0)
						{
							McsUtility.Models.MinersModel info = items[0].Tag as McsUtility.Models.MinersModel;

							byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerReset, new int[] { info.ID });
							this.Agent.AgentSend(bytes);
							MessageBox.Show("重启矿机指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
						}
					}
					else
					{
						MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
						ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
					}
				}
			};

			ToolStripMenuItem itemRestart = new ToolStripMenuItem("重启矿机");
			itemRestart.Click += new EventHandler(restartClick);
			this.RightContextMenu.Items.Add(itemRestart);

			#endregion

			#region 高级配置事件

			Action<object, EventArgs> configurationClick = delegate (object obj, EventArgs args)
			{
				if (this.Agent.IsStarted)
				{
					ListView.SelectedListViewItemCollection items = MinerList.SelectedItems;
					if (items.Count > 0)
					{
						McsUtility.Models.MinersModel info = items[0].Tag as McsUtility.Models.MinersModel;

						Action<object, ObjectEventArgs> onSuccess = delegate (object successObj, ObjectEventArgs successArgs)
						{
							if (MessageBox.Show("高级配置指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information) == DialogResult.OK)
							{
								Forms.MinerConfiguration formConfiguration = successObj as Forms.MinerConfiguration;
								if (formConfiguration != null)
									formConfiguration.Close();

								McsUtility.Models.MinersModel miner = successArgs.Data as McsUtility.Models.MinersModel;
								if (miner != null)
								{
									UpdateMinerList(miner.ID, miner);
								}
							}
						};

						Forms.MinerConfiguration form = new Forms.MinerConfiguration(this.Agent, info);
						form.OnSuccess += new EventHandler<ObjectEventArgs>(onSuccess);
						form.ShowDialog();
					}
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			ToolStripMenuItem itemConfiguration = new ToolStripMenuItem("高级配置");
			itemConfiguration.Click += new EventHandler(configurationClick);
			this.RightContextMenu.Items.Add(itemConfiguration);

			#endregion
		}

		#endregion

		#region void Init() 初始化

		private void Init()
		{
			BottomStatus_Timer.Text = "时间：" + DateTime.Now.ToString("yyyy年MM月dd日 HH:mm");
			BottomStatus_Message.Text = "请先登录系统后再进行相关操作";
			MinerList.CheckBoxes = true;

			//矿机列表行高
			ImageList image = new ImageList();
			image.ImageSize = new Size(1, 20);
			MinerList.SmallImageList = image;

			//矿机状态
			List<ComboboxListItem> items = new List<ComboboxListItem>
			{
				new ComboboxListItem{ Text = "全部", Value = "-1"},
				new ComboboxListItem{ Text = "挖矿中", Value = "2"},
				new ComboboxListItem{ Text = "在线", Value = "1"},
				new ComboboxListItem{ Text = "离线", Value = "0"}
			};
			Common.Utility.SetComboBox(this, "SearchStatus", items);

			//状态栏时间
			Action<object, EventArgs> statusTick = delegate (object obj, EventArgs args)
			{
				BottomStatus_Timer.Text = "时间：" + DateTime.Now.ToString("yyyy年MM月dd日 HH:mm");
			};
			Timer statusTimer = new Timer
			{
				Interval = 1000,
				Enabled = true
			};
			statusTimer.Tick += new EventHandler(statusTick);
			statusTimer.Start();

			//矿机状态日志
			if (System.IO.File.Exists(Common.Utility.MinerStatusLogPath))
			{
				string minerStatusLog = System.IO.File.ReadAllText(Common.Utility.MinerStatusLogPath, Encoding.UTF8);
				MinerStatusLog.Text = minerStatusLog;
			}

			//刷新矿机算力
			Action<object, EventArgs> refreshHashrateTick = delegate (object obj, EventArgs args)
			{
				//发送数据
				if (this.Agent.IsStarted && this.AllowRefreshHashrate)
				{
					//设置是否允许刷新算力信息，不允许刷新时终止执行
					if (this.AllowTimerRefreshHashrate)
						this.AllowTimerRefreshHashrate = false;
					else
						return;

					ListView.ListViewItemCollection itemsMiner = MinerList.Items;
					
					foreach (ListViewItem item in itemsMiner)
					{
						McsUtility.Models.MinersModel info = item.Tag as McsUtility.Models.MinersModel;
						if (info != null)
						{
							byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerGetRedisData, new int[] { info.ID });
							this.Agent.AgentSend(bytes);
						}
					}
				}
			};
			Timer refreshHashrateTimer = new Timer
			{
				Interval = 2000,
				Enabled = true
			};
			refreshHashrateTimer.Tick += new EventHandler(refreshHashrateTick);
			refreshHashrateTimer.Start();
		}

		#endregion

		#region void InitAgent() 初始化Agent

		#region void InitAgent()

		private void InitAgent()
		{
			//this.Agent.LocalIp = MyIp();
			//this.Agent.ServerIp = "192.168.1.38";
			//this.Agent.ServerPort = 12345;
			this.Agent.OnMessage += new EventHandler<MsgEventArgs>(Agent_OnMessage);
			this.Agent.OnReceive += new EventHandler<RcvEventArgs>(Agent_OnReceive);
			this.Agent.OnShutdown += new EventHandler<EventArgs>(Agent_OnShutdown);
			this.Agent.OnExceptionClose += new EventHandler<EventArgs>(Agent_OnExceptionClose);

			this.Agent.OnNodeServerMinerManagerGetStaffs += new EventHandler<ByteEventArgs>(Agent_OnNodeServerMinerManagerGetStaffs);
		}

		#endregion

		#region void Agent_OnReceive(object sender, RcvEventArgs e)

		private void Agent_OnReceive(object sender, RcvEventArgs e)
		{
			var proto = ProtocolHelper.GetProtoType(e.Buffer, body: out byte[] body);
			//string json = System.Text.Encoding.UTF8.GetString(body);

			switch (proto)
			{
				case ProtoType.NodeServerManagerLogin://NodeServer回应管理端登录
					ProcessNodeServerManagerLogin(body);
					break;
				case ProtoType.NodeServerManagerGetMiners://NodeServer回应管理端请求的矿机搜索信息
					ProcessNodeServerManagerGetMiners(body);
					break;
				case ProtoType.NodeServerMinerManagerGetRedisData://NodeServer响应管理端请求Redis数据
					ProcessNodeServerMinerManagerGetRedisData(body);
					break;
				case ProtoType.NodeServerMinerLoginToManager://NodeServer下发矿机登录信息给管理端
					ProcessNodeServerMinerLoginToManager(body);
					break;
				case ProtoType.NodeServerMinerLogoutToManager://NodeServer下发矿机离线信息给管理端
					ProcessNodeServerMinerLogoutToManager(body);
					break;
				case ProtoType.MinerClientStartMiningToManager://矿机挖矿状态下发给管理端
					ProcessMinerClientStartMiningToManager(body);
					break;
				case ProtoType.MinerClientEndMiningToManager://矿机停止挖矿状态下发给管理端
					ProcessMinerClientEndMiningToManager(body);
					break;
				case ProtoType.NodeServerMinerManagerDelMiner://删除矿机
					ProcessNodeServerMinerManagerDelMiner(body);
					break;
				case ProtoType.MinerReAccept://NodeServer通知端重连NodeServer
					ProcessMinerReAccept(body);
					break;
				case ProtoType.NodeServerWarnToMinerManager://NodeServer下发报警信息
					ProcessNodeServerWarnToMinerManager(body);
					break;
				case ProtoType.NodeServerManagerGetMinerModel://NodeServer回应管理端请求的矿机搜索信息
					ProcessNodeServerManagerGetMinerModel(body);
					break;
				case ProtoType.MinerManagerDownToManager://管理端收到指令，断开连接
					ProcessMinerManagerDownToManager();
					break;
			}
		}
		
		#region void ProcessNodeServerManagerLogin(byte[] body) NodeServer回应管理端登录

		private void ProcessNodeServerManagerLogin(byte[] body)
		{
			//NodeServerManagerLogin = 8 NodeServer回应管理端登录

			McsUtility.Models.ResultModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.ResultModel>(body);
			if (result.success)
			{
				McsUtility.Models.LoginResultModel info = TomNet.Utility.Data.JsonHelper.FromJson<McsUtility.Models.LoginResultModel>(result.data.ToString());
				Common.Data.Staff = info.Staff;
				Common.Data.UserCurrency = info.Currencys;
				this.FormLogin?.HandleFeedback(true);

				SetControlStatus(true);
				ShowStatusMessage("");
				ShowStatusLoginMessage("登录用户：" + info.Name);
				LoadSearchData();
				Search(1, this.PageSize);
				RefreshStaffDisplay();

				//更新登录状态
				Common.Data.IsLogin = true;

				//无客户经理时请求客户经理列表
				if (info.Staff.ID <= 0)
				{
					byte[] bytes = ProtocolHelper.WritePackage(ProtoType.MinerManagerGetStaffs, "");
					this.Agent.AgentSend(bytes);
				}
			}
			else
			{
				//更新登录状态
				Common.Data.IsLogin = false;

				ProcessNodeServerManagerLoginFailureHandle();
			}
		}

		private delegate void DelegateProcessNodeServerManagerLoginFailureHandle();
		private void ProcessNodeServerManagerLoginFailureHandle()
		{
			if (this.InvokeRequired)
			{
				DelegateProcessNodeServerManagerLoginFailureHandle d = new DelegateProcessNodeServerManagerLoginFailureHandle(ProcessNodeServerManagerLoginFailureHandle);
				this.BeginInvoke(d);
			}
			else
			{
				bool loginWindowIsOpen = false;
				foreach (Form form in Application.OpenForms)
				{
					if (form.Name.Equals("UserLogin", StringComparison.CurrentCultureIgnoreCase))
					{
						loginWindowIsOpen = true;
						break;
					}
				}

				if (!loginWindowIsOpen)
					MessageBox.Show("登录失败，请检查登录账号和密码是否正确。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				else
					this.FormLogin?.HandleFeedback(false);

				ClearSearchData();
				ClearMinerList();
				ShowStatusMessage("请先登录系统后再进行相关操作");
				SetControlStatus(false);
				ShowStatusLoginMessage("未登录");
				this.AllowRefreshHashrate = false;
			}
		}

		#endregion

		#region void ProcessNodeServerManagerGetMiners(byte[] body) NodeServer回应管理端请求的矿机搜索信息

		private void ProcessNodeServerManagerGetMiners(byte[] body)
		{
			//NodeServerManagerGetMiners = 29 NodeServer回应管理端请求的矿机搜索信息
			if (body != null)
			{
				McsUtility.Models.MinersResponseModel info = ProtoBufHelper.Deserialize<McsUtility.Models.MinersResponseModel>(body);
				if (info != null)
				{
					this.TotalCount = info.TotalRows;
					this.PageCount = info.TotalRows % this.PageSize > 0 ? info.TotalRows / this.PageSize + 1 : info.TotalRows / this.PageSize;

					ClearMinerList();
					InsertMinerList(info.Miners);
					ShowPageMessage();
					this.AllowRefreshHashrate = true;
				}
			}
			else
			{
				ClearMinerList();
				InsertMinerList(new List<McsUtility.Models.MinersModel>());
				ShowPageMessage();
				this.AllowRefreshHashrate = true;
			}
		}

		#endregion

		#region void ProcessNodeServerMinerManagerGetRedisData(byte[] body) NodeServer响应管理端请求Redis数据

		private void ProcessNodeServerMinerManagerGetRedisData(byte[] body)
		{
			//NodeServerMinerManagerGetRedisData = 54 NodeServer响应管理端请求Redis数据

			//允许刷新算力时执行
			if (this.AllowRefreshHashrate)
			{
				List<McsUtility.Models.RedisDataModel> result = ProtocolHelper.ReadPackageBody<List<McsUtility.Models.RedisDataModel>>(body);
				ShowHashrate(result);
			}
		}

		#endregion

		#region void ProcessNodeServerMinerLoginToManager(byte[] body) NodeServer下发矿机登录信息给管理端

		private void ProcessNodeServerMinerLoginToManager(byte[] body)
		{
			//NodeServerMinerLoginToManager = 56 NodeServer下发矿机登录信息给管理端

			McsUtility.Models.MinerCloseModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.MinerCloseModel>(body);
			WriteMinerStatusLog(DateTime.Now, string.Format("矿机“{0}”登录。", result.MinerName));

			McsUtility.Models.MinersModel info = new McsUtility.Models.MinersModel
			{
				ID = result.MinerID,
				MinerName = result.MinerName
			};
			InsertMinerList(new List<McsUtility.Models.MinersModel> { info });
		}

		#endregion

		#region void ProcessNodeServerMinerLogoutToManager(byte[] body) NodeServer下发矿机离线信息给管理端

		private void ProcessNodeServerMinerLogoutToManager(byte[] body)
		{
			//NodeServerMinerLogoutToManager = 58 NodeServer下发矿机离线信息给管理端

			McsUtility.Models.MinerCloseModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.MinerCloseModel>(body);
			WriteMinerStatusLog(DateTime.Now, string.Format("矿机“{0}”离线。", result.MinerName));
			UpdateMinerListForColumn(result.MinerID, 2, Common.Utility.GetStatusName(0), 0);
		}

		#endregion

		#region void ProcessMinerClientStartMiningToManager(byte[] body) 矿机挖矿状态下发给管理端

		private void ProcessMinerClientStartMiningToManager(byte[] body)
		{
			//MinerClientStartMiningToManager = 61 矿机挖矿状态下发给管理端

			McsUtility.Models.MinerClientStatusModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.MinerClientStatusModel>(body);
			WriteMinerStatusLog(DateTime.Now, string.Format("矿机“{0}”开始挖矿。", result.MinerName));

			result.Model.State = 2;
			UpdateMinerList(result.MinerId, result.Model);
		}

		#endregion

		#region void ProcessMinerClientEndMiningToManager(byte[] body) 矿机停止挖矿状态下发给管理端

		private void ProcessMinerClientEndMiningToManager(byte[] body)
		{
			//MinerClientEndMiningToManager = 70 矿机停止挖矿状态下发给管理端

			McsUtility.Models.MinerCloseModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.MinerCloseModel>(body);
			WriteMinerStatusLog(DateTime.Now, string.Format("矿机“{0}”停止挖矿。", result.MinerName));
			UpdateMinerListForColumn(result.MinerID, 2, Common.Utility.GetStatusName(1), 1);
		}

		#endregion

		#region void ProcessNodeServerMinerManagerDelMiner(byte[] body)

		private void ProcessNodeServerMinerManagerDelMiner(byte[] body)
		{
			//NodeServerMinerManagerDelMiner = 74 删除矿机

			Search(1, this.PageSize);
		}

		#endregion

		#region void ProcessMinerReAccept(byte[] body) NodeServer通知端重连NodeServer

		private void ProcessMinerReAccept(byte[] body)
		{
			//MinerReAccept = 52 NodeServer通知端重连NodeServer

			//关闭连接
			//this.Agent.Stop();
			
			McsUtility.Models.GetNodeServerResponseModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.GetNodeServerResponseModel>(body);

			//连接服务器
			Common.ConnectionServer conn = new Common.ConnectionServer(this.Agent);
			bool isStarted = conn.Connection(result.IP, (ushort)result.Port);
			if (isStarted)
			{
				McsUtility.Models.LoginModel info = new McsUtility.Models.LoginModel
				{
					LoginName = Common.Data.LoginUserName,
					LoginPass = Common.Data.LoginPassWord
				};
				byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.LoginModel>(ProtoType.MinerManagerLogin, info);
				this.Agent.AgentSend(bytes);
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "连接失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		#endregion

		#region void ProcessNodeServerWarnToMinerManager(byte[] body) NodeServer下发报警信息

		private void ProcessNodeServerWarnToMinerManager(byte[] body)
		{
			//NodeServerWarnToMinerManager = 88 NodeServer下发报警信息
						
			McsUtility.Models.WarnModel result = ProtocolHelper.ReadPackageBody<McsUtility.Models.WarnModel>(body);
			WarnPopup(result);
		}

		private delegate void DelegateWarnPopup(McsUtility.Models.WarnModel info);

		private void WarnPopup(McsUtility.Models.WarnModel info)
		{
			if (this.InvokeRequired)
			{
				DelegateWarnPopup d = new FrmMain.DelegateWarnPopup(WarnPopup);
				this.BeginInvoke(d, info);
			}
			else
			{
				Forms.FrmPopup form = null;
				string warnMessage = string.Empty;
				string logMessage = string.Empty;

				Action<object, EventArgs> onShowClick = delegate (object obj, EventArgs args)
				{
					byte[] sendBytes = ProtocolHelper.WritePackage(ProtoType.MinerManagerGetMinerModel, TomNet.Utility.Data.JsonHelper.ToJson(info.MinerID));
					this.Agent.AgentSend(sendBytes);

					if (form != null)
						form.Close();
				};

				switch (info.WarnType)
				{
					case 0://高温报警
						logMessage= "矿机“" + info.MinerName + "”高温报警：" + info.WarnMessage;
						warnMessage = "矿机“" + info.MinerName + "”高温报警。" + Environment.NewLine + info.WarnMessage;
						form = new Forms.FrmPopup("异常报警", "矿机温度过高报警", warnMessage, 60 * 3);
						form.SetButton(true, "查看矿机", onShowClick);
						form.Show();
						break;
					case 1://低算力报警
						logMessage = "矿机“" + info.MinerName + "”低算力报警：" + info.WarnMessage;
						warnMessage = "矿机“" + info.MinerName + "”低算力报警。" + Environment.NewLine + info.WarnMessage;
						form = new Forms.FrmPopup("异常报警", "矿机算力过低报警", warnMessage, 60 * 3);
						form.SetButton(true, "查看矿机", onShowClick);
						form.Show();
						break;
				}

				//写入日志
				if (!string.IsNullOrWhiteSpace(logMessage))
					WriteMinerStatusLog(DateTime.Now, logMessage);
			}
		}

		#endregion

		#region void ProcessNodeServerManagerGetMinerModel(byte[] body) NodeServer回应管理端请求的矿机搜索信息

		private void ProcessNodeServerManagerGetMinerModel(byte[] body)
		{
			//NodeServerManagerGetMinerModel = 90 NodeServer回应管理端请求的矿机搜索信息

			if (body != null)
			{
				McsUtility.Models.MinersModel info = ProtoBufHelper.Deserialize<McsUtility.Models.MinersModel>(body);
				if (info != null)
				{
					InsertMinerList(new List<McsUtility.Models.MinersModel> { info });
					this.AllowRefreshHashrate = true;
				}
			}
		}

		#endregion

		#region void ProcessMinerManagerDownToManager() 管理端收到指令，断开连接

		private delegate void DelegateProcessMinerManagerDownToManager();

		private void ProcessMinerManagerDownToManager()
		{
			if (this.InvokeRequired)
			{
				DelegateProcessMinerManagerDownToManager d = new DelegateProcessMinerManagerDownToManager(ProcessMinerManagerDownToManager);
				this.BeginInvoke(d);
			}
			else
			{
				this.Agent.Stop();

				//更新登录状态
				Common.Data.IsLogin = false;

				string msg = "您的账号在另一地点登录，您被迫下线。" + Environment.NewLine + Environment.NewLine
					+ "如果这不是您本人的操作，那么您的密码很可能已经泄漏。建议您修改密码。";
				Forms.FrmPopup form = new Forms.FrmPopup("提示", "强制下线", msg);
				form.Show();
			}
		}

		#endregion

		#endregion

		#region void Agent_OnNodeServerMinerManagerGetStaffs(byte[] body)

		private void Agent_OnNodeServerMinerManagerGetStaffs(object sender,ByteEventArgs e)
		{
			List<McsUtility.Models.StaffModel> infosStaff = ProtocolHelper.ReadPackageBody<List<McsUtility.Models.StaffModel>>(e.Bytes);

			//获取默认客户经理
			string staffId = System.Configuration.ConfigurationManager.AppSettings["StaffId"];
			if (string.IsNullOrWhiteSpace(staffId))
				staffId = "2";

			int index = infosStaff.FindIndex(p => p.ID.ToString() == staffId);
			if (index >= 0)
			{
				Common.Data.Staff = infosStaff[index];
				RefreshStaffDisplay();
			}
		}

		#endregion

		#region void Agent_OnExceptionClose(object sender,EventArgs e)

		private void Agent_OnExceptionClose(object sender, EventArgs e)
		{
			if (Common.Data.IsLogin)
				OpenFormReconnect();

			//更新登录状态
			Common.Data.IsLogin = false;

			Common.Data.UserCurrency = new List<McsUtility.Models.CurrencysModel>();

			ClearSearchData();
			ClearMinerList();
			ShowStatusMessage("");
			SetControlStatus(false);
			ShowStatusLoginMessage("未登录");
			this.AllowRefreshHashrate = false;
		}

		#endregion

		#region void Agent_OnShutdown(object sender, EventArgs e)

		private void Agent_OnShutdown(object sender, EventArgs e)
		{
			//更新登录状态
			Common.Data.IsLogin = false;

			Common.Data.UserCurrency = new List<McsUtility.Models.CurrencysModel>();
			
			ClearSearchData();
			ClearMinerList();
			ShowStatusMessage("");
			SetControlStatus(false);
			ShowStatusLoginMessage("未登录");
			this.AllowRefreshHashrate = false;
		}

		#endregion

		private void Agent_OnMessage(object sender, MsgEventArgs e)
		{
			System.Diagnostics.Debug.WriteLine(e.Message);
		}

		#endregion

		#region TopMenu按钮点击事件

		private void TopMenu_User_Login_Click(object sender, EventArgs e)
		{
			#region onHandle事件

			Action<object, LoginHandleEventArgs> onHandle = delegate (object obj, LoginHandleEventArgs args)
			{
				//连接服务器
				if (!this.Agent.IsStarted)
				{
					Common.ConnectionServer conn = new Common.ConnectionServer(this.Agent);
					conn.Connection();
				}

				//发送数据
				if (this.Agent.IsStarted)
				{
					Common.Data.LoginUserName = args.UserName;
					Common.Data.LoginPassWord = args.PassWord;

					McsUtility.Models.LoginModel info = new McsUtility.Models.LoginModel
					{
						LoginName = Common.Data.LoginUserName,
						LoginPass = Common.Data.LoginPassWord
					};
					byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.LoginModel>(ProtoType.MinerManagerLogin, info);
					this.Agent.AgentSend(bytes);
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			};

			#endregion

			#region onCancel事件

			Action<object, EventArgs> onCancel = delegate (object obj, EventArgs args)
			{
				if (this.FormLogin != null)
				{
					this.FormLogin.Dispose();
					this.FormLogin = null;
				}
			};

			#endregion

			if (this.FormLogin == null)
			{
				this.FormLogin = new Forms.UserLogin();
				this.FormLogin.OnHandle += new EventHandler<LoginHandleEventArgs>(onHandle);
				this.FormLogin.OnCancel += new EventHandler<EventArgs>(onCancel);
				this.FormLogin.ShowDialog();
			}
			else
			{
				this.FormLogin.ShowDialog();
			}
		}

		private void TopMenu_User_Logout_Click(object sender, EventArgs e)
		{
			this.Agent.Stop();
		}

		private void TopMenu_User_Register_Click(object sender, EventArgs e)
		{
			Forms.UserRegister form = new Forms.UserRegister(this.Agent);
			form.ShowDialog();
		}

		private void TopMenu_User_ForgotPassWord_Click(object sender, EventArgs e)
		{
			Forms.UserForgotPassword form = new Forms.UserForgotPassword(this.Agent);
			form.ShowDialog();
		}

		private void TopMenu_User_ChangeStaff_Click(object sender, EventArgs e)
		{
			Action<object, EventArgs> onSuccess = delegate (object obj, EventArgs args)
			{
				RefreshStaffDisplay();
			};

			Forms.UserChangeStaff form = new Forms.UserChangeStaff(this.Agent);
			form.OnSuccess += new EventHandler<EventArgs>(onSuccess);
			form.ShowDialog();
		}

		private void TopMenu_Miner_Wallet_Click(object sender, EventArgs e)
		{
			Action<object, EventArgs> onClose = delegate (object obj, EventArgs args)
			{
				LoadSearchData();
			};

			Forms.MinerWallet form = new Forms.MinerWallet(this.Agent);
			form.OnClose += new EventHandler<EventArgs>(onClose);
			form.ShowDialog();
		}

		#endregion

		#region MinerList按钮事件

		private void BtnCheckAll_Click(object sender, EventArgs e)
		{
			ListView.ListViewItemCollection items = MinerList.Items;
			foreach (ListViewItem item in items)
			{
				item.Checked = true;
			}
		}

		private void BtnCheckInverse_Click(object sender, EventArgs e)
		{
			ListView.ListViewItemCollection items = MinerList.Items;
			foreach (ListViewItem item in items)
			{
				item.Checked = !item.Checked;
			}
		}

		private void BtnFirstPage_Click(object sender, EventArgs e)
		{
			if (this.PageIndex > 1)
			{
				this.PageIndex = 1;

				ShowPageMessage();
				Search(this.PageIndex, this.PageSize);
			}
		}

		private void BtnBeforPage_Click(object sender, EventArgs e)
		{
			if (this.PageIndex > 1)
			{
				this.PageIndex -= 1;
				this.PageIndex = this.PageIndex >= 1 ? this.PageIndex : 1;

				ShowPageMessage();
				Search(this.PageIndex, this.PageSize);
			}
		}

		private void BtnAfterPage_Click(object sender, EventArgs e)
		{
			if (this.PageIndex < this.PageCount)
			{
				this.PageIndex += 1;
				this.PageIndex = this.PageIndex <= this.PageCount ? this.PageIndex : this.PageCount;

				ShowPageMessage();
				Search(this.PageIndex, this.PageSize);
			}
		}

		private void BtnLastPage_Click(object sender, EventArgs e)
		{
			if (this.PageIndex < this.PageCount)
			{
				this.PageIndex = this.PageCount;

				ShowPageMessage();
				Search(this.PageIndex, this.PageSize);
			}
		}

		#region void BtnBtnEditConfiguration_Click(object sender, EventArgs e)

		private void BtnBtnEditConfiguration_Click(object sender, EventArgs e)
		{
			ListView.CheckedListViewItemCollection items = MinerList.CheckedItems;

			List<McsUtility.Models.MinersModel> infos = new List<McsUtility.Models.MinersModel>();
			foreach (ListViewItem item in items)
			{
				McsUtility.Models.MinersModel info = item.Tag as McsUtility.Models.MinersModel;
				if (info != null)
				{
					infos.Add(info);
				}
			}

			if (infos.Count > 0)
			{
				Action<object, ObjectEventArgs> onSuccess = delegate (object obj, ObjectEventArgs args)
				{
					if (MessageBox.Show("修改配置指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information) == DialogResult.OK)
					{
						Forms.MinerBatchConfiguration formConfiguration = obj as Forms.MinerBatchConfiguration;
						if (formConfiguration != null)
							formConfiguration.Close();

						List<McsUtility.Models.MinersModel> miners = args.Data as List<McsUtility.Models.MinersModel>;
						if (miners != null)
						{
							foreach(McsUtility.Models.MinersModel miner in miners)
							{
								UpdateMinerList(miner.ID, miner);
							}
						}
					}
				};

				Forms.MinerBatchConfiguration form = new Forms.MinerBatchConfiguration(this.Agent, infos);
				form.OnSuccess += new EventHandler<ObjectEventArgs>(onSuccess);
				form.ShowDialog();
			}
			else
			{
				MessageBox.Show("请选择要修改配置的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		#endregion

		#region void BtnMinerRestart_Click(object sender, EventArgs e)

		private void BtnMinerRestart_Click(object sender, EventArgs e)
		{
			//发送数据
			if (this.Agent.IsStarted)
			{
				if (MessageBox.Show("确定要批量重启已经选取的矿机吗？", "重启矿机", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					ListView.CheckedListViewItemCollection items = MinerList.CheckedItems;

					List<int> ids = new List<int>();
					foreach (ListViewItem item in items)
					{
						McsUtility.Models.MinersModel info = item.Tag as McsUtility.Models.MinersModel;
						if (info != null)
						{
							ids.Add(info.ID);
						}
					}

					if (ids.Count > 0)
					{
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerReset, ids.ToArray());
						this.Agent.AgentSend(bytes);
						MessageBox.Show("重启矿机指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					else
					{
						MessageBox.Show("请选择要重启的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			}
		}

		#endregion

		#region void BtnMinerStart_Click(object sender, EventArgs e)

		private void BtnMinerStart_Click(object sender, EventArgs e)
		{
			//发送数据
			if (this.Agent.IsStarted)
			{
				if (MessageBox.Show("确定要将选取的矿机开始挖矿吗？", "开始挖矿", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					ListView.CheckedListViewItemCollection items = MinerList.CheckedItems;

					List<int> ids = new List<int>();
					foreach (ListViewItem item in items)
					{
						McsUtility.Models.MinersModel info = item.Tag as McsUtility.Models.MinersModel;
						if (info != null)
							ids.Add(info.ID);
					}

					if (ids.Count > 0)
					{
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerStartMining, ids.ToArray());
						this.Agent.AgentSend(bytes);
						MessageBox.Show("开始挖矿指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					else
					{
						MessageBox.Show("请选择要开始挖矿的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			}
		}

		#endregion

		#region void BtnMinerStop_Click(object sender, EventArgs e)

		private void BtnMinerStop_Click(object sender, EventArgs e)
		{
			//发送数据
			if (this.Agent.IsStarted)
			{
				if (MessageBox.Show("确定要将选取的矿机停止挖矿吗？", "停止挖矿", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					ListView.CheckedListViewItemCollection items = MinerList.CheckedItems;

					List<int> ids = new List<int>();
					foreach (ListViewItem item in items)
					{
						McsUtility.Models.MinersModel info = item.Tag as McsUtility.Models.MinersModel;
						if (info != null)
							ids.Add(info.ID);
					}

					if (ids.Count > 0)
					{
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerEndMining, ids.ToArray());
						this.Agent.AgentSend(bytes);
						MessageBox.Show("停止挖矿指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					else
					{
						MessageBox.Show("请选择要停止挖矿的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			}
		}

		#endregion

		#region void BtnMinerDelete_Click(object sender, EventArgs e)

		private void BtnMinerDelete_Click(object sender, EventArgs e)
		{
			//发送数据
			if (this.Agent.IsStarted)
			{
				if (MessageBox.Show("确定要删除选取的矿机吗？", "删除矿机", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.OK)
				{
					ListView.CheckedListViewItemCollection items = MinerList.CheckedItems;

					List<int> ids = new List<int>();
					foreach (ListViewItem item in items)
					{
						McsUtility.Models.MinersModel info = item.Tag as McsUtility.Models.MinersModel;
						if (info != null)
							ids.Add(info.ID);
					}

					if (ids.Count > 0)
					{
						byte[] bytes = ProtocolHelper.WritePackage<int[]>(ProtoType.MinerManagerDelMiner, ids.ToArray());
						this.Agent.AgentSend(bytes);
						MessageBox.Show("删除矿机指令下达成功。", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
					}
					else
					{
						MessageBox.Show("请选择要删除的矿机。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					}
				}
			}
			else
			{
				MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
				ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
			}
		}

		#endregion

		#region void BtnStatusInfo_Click(object sender, EventArgs e)

		private void BtnStatusInfo_Click(object sender, EventArgs e)
		{
			Forms.MinerStatusInfo form = new Forms.MinerStatusInfo();
			form.ShowDialog();
		}

		#endregion

		#region void MinerList_MouseClick(object sender, MouseEventArgs e)

		private void MinerList_MouseClick(object sender, MouseEventArgs e)
		{
			ListViewHitTestInfo view = MinerList.HitTest(e.Location);

			//if (e.Button == MouseButtons.Left)
			//{
			//	view.Item.Checked = !view.Item.Checked;
			//}

			if (e.Button == MouseButtons.Right)
			{
				this.RightContextMenu.Show(MinerList, e.Location);
			}
		}

		#endregion

		#region void MinerList_MouseDoubleClick(object sender, MouseEventArgs e)

		private void MinerList_MouseDoubleClick(object sender, MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Left)
			{
				ListViewHitTestInfo view = MinerList.HitTest(e.Location);

				//打开窗体
				if (view.Item != null)
				{
					view.Item.Checked = !view.Item.Checked;

					McsUtility.Models.MinersModel info = view.Item.Tag as McsUtility.Models.MinersModel;

					Action<object, EventArgs> onClose = delegate (object obj, EventArgs args)
					{
						this.AllowRefreshHashrate = true;
					};

					this.AllowRefreshHashrate = false;
					Forms.MinerHashrate form = new Forms.MinerHashrate(this.Agent, info.ID, info.MinerName, info.FirstCoin, info.SecondCoin);
					form.OnClose += new EventHandler<EventArgs>(onClose);
					form.ShowDialog();
				}
			}
		}

		#endregion

		#endregion

		#region void BtnSearch_Click(object sender, EventArgs e)

		private void BtnSearch_Click(object sender, EventArgs e)
		{
			this.PageIndex = 1;
			Search(this.PageIndex, this.PageSize);
		}

		#endregion

		#region void SearchCurrency_SelectedIndexChanged(object sender, EventArgs e)

		private void SearchCurrency_SelectedIndexChanged(object sender, EventArgs e)
		{
			SearchCurrencyChange();
		}

		#endregion

		#region void BtnClearMinerStatusLog_Click(object sender, EventArgs e)

		private void BtnClearMinerStatusLog_Click(object sender, EventArgs e)
		{
			MinerStatusLog.Text = "";
			System.IO.File.WriteAllText(Common.Utility.MinerStatusLogPath, "", Encoding.UTF8);
		}

		#endregion



		#region void ShowStatusMessage(string message) 显示状态栏信息。

		private delegate void DelegateShowStatusMessage(string message);

		/// <summary>
		/// 显示状态栏信息。
		/// </summary>
		/// <param name="message"></param>
		private void ShowStatusMessage(string message)
		{
			if (BottomStatus.InvokeRequired)
			{
				DelegateShowStatusMessage d = new DelegateShowStatusMessage(ShowStatusMessage);
				this.BeginInvoke(d, message);
			}
			else
			{
				BottomStatus_Message.Text = message;
			}
		}

		#endregion

		#region void ShowStatusLoginMessage(string message) 显示状态栏登录信息。

		private delegate void DelegateShowStatusLoginMessage(string message);

		/// <summary>
		/// 显示状态栏登录信息。
		/// </summary>
		/// <param name="message"></param>
		private void ShowStatusLoginMessage(string message)
		{
			if (BottomStatus.InvokeRequired)
			{
				DelegateShowStatusLoginMessage d = new DelegateShowStatusLoginMessage(ShowStatusLoginMessage);
				this.BeginInvoke(d, message);
			}
			else
			{
				BottomStatus_LoginMessage.Text = message;
			}
		}

		#endregion

		#region void SetControlStatus(bool isLogin) 设置控件在不同登录状态时的显示方式。

		private delegate void DelegateSetControlStatus(bool isLogin);

		/// <summary>
		/// 设置控件在不同登录状态时的显示方式。
		/// </summary>
		/// <param name="isLogin"></param>
		private void SetControlStatus(bool isLogin)
		{
			if (this.InvokeRequired)
			{
				DelegateSetControlStatus d = new DelegateSetControlStatus(SetControlStatus);
				this.BeginInvoke(d, isLogin);
			}
			else
			{
				if (isLogin)
				{
					TopMenu_User_Login.Visible = false;
					TopMenu_User_Logout.Visible = true;
					TopMenu_User_ChangeStaff.Visible = true;
					TopMenu_Miner_Wallet.Enabled = true;

					BtnSearch.Enabled = true;
					SearchCurrency.Enabled = true;
					SearchWallet.Enabled = true;
					SearchPool.Enabled = true;
					SearchStatus.Enabled = true;

					BtnCheckAll.Enabled = true;
					BtnCheckInverse.Enabled = true;
					BtnEditConfiguration.Enabled = true;
					BtnMinerRestart.Enabled = true;
					BtnMinerStart.Enabled = true;
					BtnMinerStop.Enabled = true;
					BtnMinerDelete.Enabled = true;
					BtnStatusInfo.Enabled = true;

					BtnFirstPage.Enabled = true;
					BtnBeforPage.Enabled = true;
					BtnAfterPage.Enabled = true;
					BtnLastPage.Enabled = true;
				}
				else
				{
					TopMenu_User_Login.Visible = true;
					TopMenu_User_Logout.Visible = false;
					TopMenu_User_ChangeStaff.Visible = false;
					TopMenu_Miner_Wallet.Enabled = false;

					BtnSearch.Enabled = false;
					SearchCurrency.Enabled = false;
					SearchWallet.Enabled = false;
					SearchPool.Enabled = false;
					SearchStatus.Enabled = false;

					BtnCheckAll.Enabled = false;
					BtnCheckInverse.Enabled = false;
					BtnEditConfiguration.Enabled = false;
					BtnMinerRestart.Enabled = false;
					BtnMinerStart.Enabled = false;
					BtnMinerStop.Enabled = false;
					BtnMinerDelete.Enabled = false;
					BtnStatusInfo.Enabled = false;
					PageMessage.Text = "";

					BtnFirstPage.Enabled = false;
					BtnBeforPage.Enabled = false;
					BtnAfterPage.Enabled = false;
					BtnLastPage.Enabled = false;
				}
			}
		}

		#endregion

		#region void LoadSearchData() 加载搜索项。

		/// <summary>
		/// 加载搜索项。
		/// </summary>
		private void LoadSearchData()
		{
			//币种信息
			List<ComboboxListItem> itemsCurrency = new List<ComboboxListItem>();
			itemsCurrency.Add(new ComboboxListItem { Text = "全部", Value = "" });
			foreach (McsUtility.Models.CurrencysModel info in Common.Data.UserCurrency)
			{
				itemsCurrency.Add(new ComboboxListItem { Text = info.Remark, Value = info.Name });
			}
			Common.Utility.SetComboBox(this, "SearchCurrency", itemsCurrency);
		}

		#endregion

		#region void ClearSearchData() 清空搜索项。

		/// <summary>
		/// 清空搜索项。
		/// </summary>
		private void ClearSearchData()
		{
			Common.Utility.SetComboBox(this, "SearchCurrency", new List<ComboboxListItem>());
			Common.Utility.SetComboBox(this, "SearchWallet", new List<ComboboxListItem>());
			Common.Utility.SetComboBox(this, "SearchPool", new List<ComboboxListItem>());
		}

		#endregion

		#region void SearchCurrencyChange() 根据币种加载钱包信息及矿池信息。

		private delegate void DelegateSearchCurrencyChange();

		/// <summary>
		/// 根据币种加载钱包信息及矿池信息。
		/// </summary>
		private void SearchCurrencyChange()
		{
			if (SearchCurrency.InvokeRequired)
			{
				DelegateSearchCurrencyChange d = new DelegateSearchCurrencyChange(SearchCurrencyChange);
				this.BeginInvoke(d);
			}
			else
			{
				ComboboxListItem item = SearchCurrency.SelectedItem as ComboboxListItem;
				if (item != null && !string.IsNullOrWhiteSpace(item.Value))
				{
					McsUtility.Models.CurrencysModel info = Common.Data.UserCurrency.Where(p => p.Name.Equals(item.Value, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
					if (info != null)
					{
						//钱包信息
						List<ComboboxListItem> itemsWallet = new List<ComboboxListItem>
						{
							new ComboboxListItem{ Text = "全部",Value = "" }
						};

						//矿池信息
						List<ComboboxListItem> itemsPool = new List<ComboboxListItem>
						{
							new ComboboxListItem{ Text = "全部",Value = "" }
						};

						foreach (McsUtility.Models.WalletsModel infoWallet in info.Wallets)
						{
							itemsWallet.Add(new ComboboxListItem { Text = infoWallet.Address, Value = infoWallet.Address });
						}

						foreach (McsUtility.Models.WalletsModel infoPool in info.OrePools)
						{
							itemsPool.Add(new ComboboxListItem { Text = !string.IsNullOrWhiteSpace(infoPool.Remark) ? infoPool.Remark : infoPool.Address, Value = infoPool.Address });
						}

						Common.Utility.SetComboBox(this, "SearchWallet", itemsWallet);
						Common.Utility.SetComboBox(this, "SearchPool", itemsPool);
					}
				}
				else
				{
					Common.Utility.SetComboBox(this, "SearchWallet", new List<ComboboxListItem> { new ComboboxListItem { Text = "全部", Value = "" } });
					Common.Utility.SetComboBox(this, "SearchPool", new List<ComboboxListItem> { new ComboboxListItem { Text = "全部", Value = "" } });
				}
			}
		}

		#endregion

		#region MinerList操作方法

		#region void InsertMinerList(List<McsUtility.Models.MinersModel> infos) 添加矿机信息。

		private delegate void DelegateInsertMinerList(List<McsUtility.Models.MinersModel> infos);

		/// <summary>
		/// 添加矿机信息。
		/// </summary>
		/// <param name="infos"></param>
		private void InsertMinerList(List<McsUtility.Models.MinersModel> infos)
		{
			if (infos == null) return;

			if (this.InvokeRequired)
			{
				DelegateInsertMinerList d = new DelegateInsertMinerList(InsertMinerList);
				this.BeginInvoke(d, infos);
			}
			else
			{
				foreach (McsUtility.Models.MinersModel info in infos)
				{
					int index = -1;
					for (int i = 0; i < MinerList.Items.Count; i++)
					{
						McsUtility.Models.MinersModel infoMiner = MinerList.Items[i].Tag as McsUtility.Models.MinersModel;
						if (infoMiner.ID == info.ID)
						{
							index = i;
							break;
						}
					}
					if (index < 0)
					{
						if ((SearchCurrency.SelectedValue.ToString() == "" || SearchCurrency.SelectedValue.ToString().Equals(info.FirstCoin, StringComparison.CurrentCultureIgnoreCase) || SearchCurrency.SelectedValue.ToString().Equals(info.SecondCoin, StringComparison.CurrentCultureIgnoreCase))
							&& (SearchPool.SelectedValue.ToString() == "" || SearchPool.SelectedValue.ToString().Equals(info.FirstPool, StringComparison.CurrentCultureIgnoreCase) || SearchPool.SelectedValue.ToString().Equals(info.SecondPool, StringComparison.CurrentCultureIgnoreCase))
							&& (SearchWallet.SelectedValue.ToString() == "" || SearchWallet.SelectedValue.ToString().Equals(info.FirstWallet, StringComparison.CurrentCultureIgnoreCase) || SearchWallet.SelectedValue.ToString().Equals(info.SecondWallet, StringComparison.CurrentCultureIgnoreCase))
							)
						{
							string statusName = Common.Utility.GetStatusName(info.State);

							string poolName = info.FirstPool;
							int currencyIndex = Common.Data.UserCurrency.FindIndex(p => p.Name.Equals(info.FirstCoin, StringComparison.CurrentCultureIgnoreCase));
							if (currencyIndex >= 0)
							{
								int poolIndex = Common.Data.UserCurrency[currencyIndex].OrePools.FindIndex(p => p.Address.Equals(info.FirstPool, StringComparison.CurrentCultureIgnoreCase));
								if (poolIndex >= 0 && !string.IsNullOrWhiteSpace(Common.Data.UserCurrency[currencyIndex].OrePools[poolIndex].Remark))
									poolName = Common.Data.UserCurrency[currencyIndex].OrePools[poolIndex].Remark;
							}
							
							string[] array = new string[] {
								"", info.MinerName, statusName, info.FirstCoin, poolName, info.FirstWallet,
								"", "", info.Dcri, "", "", info.Second ? info.SecondCoin : "", info.Second ? info.SecondWallet : ""
							};

							ListViewItem item = new ListViewItem(array)
							{
								UseItemStyleForSubItems = false,
								Tag = info
							};

							switch (info.State)
							{
								case 0: item.SubItems[2].ForeColor = Color.FromArgb(0, 0, 0); break;
								case 1: item.SubItems[2].ForeColor = Color.FromArgb(34, 199, 165); break;
								case 2: item.SubItems[2].ForeColor = Color.FromArgb(21, 181, 243); break;
							}

							MinerList.Items.Add(item);
						}
					}
					else
					{
						UpdateMinerList(info.UserID, info);
					}
				}
			}
		}

		#endregion
		
		#region void UpdateMinerList(int minerId, McsUtility.Models.MinerClientStatusModel info) 更新矿机信息。

		private delegate void DelegateUpdateMinerList(int minerId, McsUtility.Models.MinersModel info);

		/// <summary>
		/// 更新矿机信息。
		/// </summary>
		/// <param name="minerId">矿机Id</param>
		/// <param name="info">矿机信息</param>
		private void UpdateMinerList(int minerId, McsUtility.Models.MinersModel info)
		{
			if (this.InvokeRequired)
			{
				DelegateUpdateMinerList d = new DelegateUpdateMinerList(UpdateMinerList);
				this.BeginInvoke(d, minerId, info);
			}
			else
			{
				int index = -1;
				for (int i = 0; i < MinerList.Items.Count; i++)
				{
					McsUtility.Models.MinersModel infoMiner = MinerList.Items[i].Tag as McsUtility.Models.MinersModel;
					if (infoMiner.ID == minerId)
					{
						index = i;
						break;
					}
				}

				if (index >= 0)
				{
					string poolName = info.FirstPool;
					int currencyIndex = Common.Data.UserCurrency.FindIndex(p => p.Name.Equals(info.FirstCoin, StringComparison.CurrentCultureIgnoreCase));
					if (currencyIndex >= 0)
					{
						int poolIndex = Common.Data.UserCurrency[currencyIndex].OrePools.FindIndex(p => p.Address.Equals(info.FirstPool, StringComparison.CurrentCultureIgnoreCase));
						if (poolIndex >= 0 && !string.IsNullOrWhiteSpace(Common.Data.UserCurrency[currencyIndex].OrePools[poolIndex].Remark))
							poolName = Common.Data.UserCurrency[currencyIndex].OrePools[poolIndex].Remark;
					}

					//赋值显示内容
					MinerList.Items[index].SubItems[1].Text = info.MinerName;
					MinerList.Items[index].SubItems[2].Text = Common.Utility.GetStatusName(info.State);
					MinerList.Items[index].SubItems[3].Text = info.FirstCoin;
					MinerList.Items[index].SubItems[4].Text = poolName;
					MinerList.Items[index].SubItems[5].Text = info.FirstWallet;
					MinerList.Items[index].SubItems[11].Text = !string.IsNullOrWhiteSpace(info.SecondPool) && !string.IsNullOrWhiteSpace(info.SecondWallet) ? info.SecondCoin : "";
					MinerList.Items[index].SubItems[12].Text = !string.IsNullOrWhiteSpace(info.SecondCoin) && !string.IsNullOrWhiteSpace(info.SecondPool) ? info.SecondWallet : "";

					//赋值Tag
					McsUtility.Models.MinersModel infoMiner = MinerList.Items[index].Tag as McsUtility.Models.MinersModel;
					if (infoMiner != null)
					{
						infoMiner.MinerName = MinerList.Items[index].SubItems[1].Text;
						infoMiner.State = info.State;
						infoMiner.AutoName = info.AutoName;
						infoMiner.AutoUpdate = info.AutoUpdate;
						infoMiner.FirstCoin = MinerList.Items[index].SubItems[3].Text;
						infoMiner.FirstPool = info.FirstPool;
						infoMiner.BackupPool = info.BackupPool;
						infoMiner.FirstWallet = MinerList.Items[index].SubItems[5].Text;
						infoMiner.Second = info.Second;
						infoMiner.SecondCoin = info.SecondCoin;
						infoMiner.SecondPool = MinerList.Items[index].SubItems[6].Text;
						infoMiner.SecondWallet = MinerList.Items[index].SubItems[7].Text;
						infoMiner.Dcri = info.Dcri;
						infoMiner.AdvParams = info.AdvParams;
						infoMiner.MinFan = info.MinFan;
						infoMiner.MaxFan = info.MaxFan;
						infoMiner.MinTemp = info.MinTemp;
						infoMiner.MaxTemp = info.MaxTemp;
						infoMiner.HighTempStrategy = info.HighTempStrategy;
						infoMiner.HighTempWarn = info.HighTempWarn;
						infoMiner.LowStrengthWarn = info.LowStrengthWarn;
						infoMiner.MinSpeed = info.MinSpeed;
						infoMiner.CoreType = info.CoreType;
						infoMiner.Eres = info.Eres;
					}

					//设置状态文本的颜色
					MinerList.Items[index].UseItemStyleForSubItems = false;
					switch (info.State)
					{
						case 0: MinerList.Items[index].SubItems[2].ForeColor = Color.FromArgb(0, 0, 0); break;
						case 1: MinerList.Items[index].SubItems[2].ForeColor = Color.FromArgb(34, 199, 165); break;
						case 2: MinerList.Items[index].SubItems[2].ForeColor = Color.FromArgb(21, 181, 243); break;
					}
				}
			}
		}

		#endregion

		#region void UpdateMinerListForColumn(int minerId, int columnIndex, string text, object value) 更新某列的矿机信息。

		private delegate void DelegateUpdateMinerListForColumn(int minerId, int columnIndex, string text, object value);

		/// <summary>
		/// 更新某列的矿机信息。
		/// </summary>
		/// <param name="minerId">矿机Id</param>
		/// <param name="columnIndex">列索引号</param>
		/// <param name="text">要显示的信息</param>
		/// <param name="value"></param>
		private void UpdateMinerListForColumn(int minerId, int columnIndex, string text, object value)
		{
			if (this.InvokeRequired)
			{
				DelegateUpdateMinerListForColumn d = new DelegateUpdateMinerListForColumn(UpdateMinerListForColumn);
				this.BeginInvoke(d, minerId, columnIndex, text, value);
			}
			else
			{
				int index = -1;
				for (int i = 0; i < MinerList.Items.Count; i++)
				{
					McsUtility.Models.MinersModel infoMiner = MinerList.Items[i].Tag as McsUtility.Models.MinersModel;
					if (infoMiner.ID == minerId)
					{
						index = i;
						break;
					}
				}

				if (index >= 0)
				{
					MinerList.Items[index].SubItems[columnIndex].Text = text;

					//更新状态时执行
					if (columnIndex == 2)
					{
						int status = -1;
						if (value != null && int.TryParse(value.ToString(), out status))
						{
							//赋值Tag
							McsUtility.Models.MinersModel infoMiner = MinerList.Items[index].Tag as McsUtility.Models.MinersModel;
							if (infoMiner != null)
								infoMiner.State = status;

							//设置状态文本的颜色
							MinerList.Items[index].UseItemStyleForSubItems = false;
							switch (status)
							{
								case 0: MinerList.Items[index].SubItems[2].ForeColor = Color.FromArgb(0, 0, 0); break;
								case 1: MinerList.Items[index].SubItems[2].ForeColor = Color.FromArgb(34, 199, 165); break;
								case 2: MinerList.Items[index].SubItems[2].ForeColor = Color.FromArgb(21, 181, 243); break;
							}
						}
					}
				}
			}
		}

		#endregion

		#region void RemoveMinerList(int minerId) 清除矿机列表中的矿机信息。

		private delegate void DelegateRemoveMinerList(int minerId);

		/// <summary>
		/// 清除矿机列表中的矿机信息。
		/// </summary>
		/// <param name="minerId">矿机Id</param>
		private void RemoveMinerList(int minerId)
		{
			if (this.InvokeRequired)
			{
				DelegateRemoveMinerList d = new DelegateRemoveMinerList(RemoveMinerList);
				this.BeginInvoke(d, minerId);
			}
			else
			{
				for (int i = 0; i < MinerList.Items.Count; i++)
				{
					McsUtility.Models.MinersModel info = MinerList.Items[i].Tag as McsUtility.Models.MinersModel;
					if (info.ID == minerId)
					{
						MinerList.Items.Remove(MinerList.Items[i]);
						break;
					}
				}
			}
		}

		#endregion

		#region void ClearMinerList() 清空矿机列表中的矿机信息。

		private delegate void DelegateClearMinerList();

		/// <summary>
		/// 清空矿机列表中的矿机信息。
		/// </summary>
		private void ClearMinerList()
		{
			if (this.InvokeRequired)
			{
				DelegateClearMinerList d = new DelegateClearMinerList(ClearMinerList);
				this.BeginInvoke(d);
			}
			else
			{
				MinerList.Items.Clear();
			}
		}

		#endregion

		#endregion

		#region void Search(int pageIndex, int pageSize) 搜索矿机。

		private delegate void DelegateSearch(int pageIndex, int pageSize);

		/// <summary>
		/// 搜索矿机。
		/// </summary>
		/// <param name="pageIndex">页码</param>
		/// <param name="pageSize">显示数量</param>
		private void Search(int pageIndex, int pageSize)
		{
			if (this.InvokeRequired)
			{
				DelegateSearch d = new DelegateSearch(Search);
				this.BeginInvoke(d, PageIndex, PageSize);
			}
			else
			{
				//发送数据
				if (this.Agent.IsStarted)
				{
					McsUtility.Models.MinersRequestModel info = new McsUtility.Models.MinersRequestModel
					{
						State = SearchStatus.SelectedValue.ToString().ConvertInt(-1),
						Currency = SearchCurrency.SelectedValue != null ? SearchCurrency.SelectedValue.ToString() : "",
						OrePool = SearchPool.SelectedValue != null ? SearchPool.SelectedValue.ToString() : "",
						Wallet = SearchWallet.SelectedValue != null ? SearchWallet.SelectedValue.ToString() : "",
						PageIndex = pageIndex,
						PageRows = pageSize
					};
					byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.MinersRequestModel>(ProtoType.MinerManagerGetMiners, info);
					this.Agent.AgentSend(bytes);
				}
				else
				{
					MessageBox.Show("服务器连接已断开，请检查网络是否畅通后重新登录。", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
					ShowStatusMessage("服务器连接已断开，请检查网络是否畅通后重新登录。");
				}
			}
		}

		#endregion

		#region void ShowPageMessage() 显示分页信息。

		private delegate void DelegateShowPageMessage();

		/// <summary>
		/// 显示分页信息。
		/// </summary>
		private void ShowPageMessage()
		{
			if (this.InvokeRequired)
			{
				DelegateShowPageMessage d = new DelegateShowPageMessage(ShowPageMessage);
				this.BeginInvoke(d);
			}
			else
			{
				PageMessage.Text = string.Format("共有矿机{0}台 第{1}页/共{2}页", this.TotalCount, this.PageIndex, this.PageCount);
			}
		}

		#endregion

		#region void ShowHashrate(List<McsUtility.Models.RedisDataModel> infos) 显示矿机算力信息。

		private delegate void DelegateShowHashrate(List<McsUtility.Models.RedisDataModel> infos);

		/// <summary>
		/// 显示矿机算力信息。
		/// </summary>
		private void ShowHashrate(List<McsUtility.Models.RedisDataModel> infos)
		{
			if (this.InvokeRequired)
			{
				DelegateShowHashrate d = new DelegateShowHashrate(ShowHashrate);
				this.BeginInvoke(d, infos);
			}
			else
			{
				ListView.ListViewItemCollection items = MinerList.Items;
				for (int i = 0; i < items.Count; i++)
				{
					McsUtility.Models.MinersModel info = (McsUtility.Models.MinersModel)items[i].Tag;
					int index = infos.FindIndex(p => p.MinerID == info.ID);
					if (index >= 0 && !string.IsNullOrWhiteSpace(infos[index].RedisData) && info.State == 2)
					{
						Models.MinerHashrate infoRedis = TomNet.Utility.Data.JsonHelper.FromJson<Models.MinerHashrate>(infos[index].RedisData);

						List<string> ta = infoRedis.Ta.ConvertListString(';');
						List<string> tb = infoRedis.Tb.ConvertListString(';');
						List<string> tmpFan = infoRedis.TmpFan.ConvertListString(';');

						decimal tmp = 0, fan = 0;
						for (int j = 0; j < tmpFan.Count; j++)
						{
							if ((decimal)j % 2 == 0)
								tmp += tmpFan[j].ConvertDecimal();
							else
								fan += tmpFan[j].ConvertDecimal();
						}

						MinerList.Items[i].SubItems[6].Text = (ta[0].ConvertDecimal() / 1000).ToString("0.000") + "MH/S";
						MinerList.Items[i].SubItems[7].Text = (tb[0].ConvertDecimal() / 1000).ToString("0.000") + "MH/S";
						MinerList.Items[i].SubItems[9].Text = tmpFan.Count > 0 ? (tmp / (tmpFan.Count / 2)).ToString("0") + "℃" : "-";
						MinerList.Items[i].SubItems[10].Text = tmpFan.Count > 0 ? (fan / (tmpFan.Count / 2)).ToString("0") + "%" : "-";

						//检测温度异常
						bool tmpException = false;
						for (int j = 0; j < tmpFan.Count; j++)
						{
							if ((decimal)j % 2 == 0 && tmpFan[j].ConvertDecimal() > 80)
								tmpException = true;
						}
						if (tmpException)
						{
							MinerList.Items[i].UseItemStyleForSubItems = false;
							MinerList.Items[i].SubItems[2].ForeColor = Color.FromArgb(255, 68, 39);
						}
						else
						{
							MinerList.Items[i].UseItemStyleForSubItems = false;
							MinerList.Items[i].SubItems[2].ForeColor = Color.FromArgb(21, 181, 243);
						}
					}
				}

				//设置是否允许刷新算力信息为允许
				this.AllowTimerRefreshHashrate = true;
			}
		}

		#endregion

		#region void WriteMinerStatusLog(string msg) 写入矿机状态日志。

		private delegate void DelegateWriteMinerStatusLog(DateTime dTime, string msg);

		/// <summary>
		/// 写入矿机状态日志。
		/// </summary>
		/// <param name="msg"></param>
		private void WriteMinerStatusLog(DateTime dTime, string msg)
		{
			if (this.InvokeRequired)
			{
				DelegateWriteMinerStatusLog d = new DelegateWriteMinerStatusLog(WriteMinerStatusLog);
				this.BeginInvoke(d, dTime, msg);
			}
			else
			{
				string logMsg = string.Empty;
				logMsg += !string.IsNullOrWhiteSpace(MinerStatusLog.Text) ? Environment.NewLine : "";
				logMsg += dTime.ToString("HH:mm:ss") + " " + msg;

				MinerStatusLog.Text += logMsg;
				MinerStatusLog.Select(MinerStatusLog.TextLength, 0);
				MinerStatusLog.ScrollToCaret();

				System.IO.File.AppendAllText(Common.Utility.MinerStatusLogPath, logMsg, Encoding.UTF8);
			}
		}

		#endregion

		#region void OpenFormReconnect() 打开掉线重连窗体。

		private delegate void DelegateOpenFormReconnect();

		/// <summary>
		/// 打开掉线重连窗体。
		/// </summary>
		private void OpenFormReconnect()
		{
			if (this.InvokeRequired)
			{
				DelegateOpenFormReconnect d = new DelegateOpenFormReconnect(OpenFormReconnect);
				this.BeginInvoke(d);
			}
			else
			{
				//关闭打开的窗体
				List<string> names = new List<string>();
				foreach (Form form in Application.OpenForms)
				{
					if (form.Name != this.Name)
						names.Add(form.Name);
				}

				foreach (string name in names)
				{
					Application.OpenForms[name].Close();
				}

				#region onHandle事件

				Action<object, EventArgs> onHandle = delegate (object obj, EventArgs args)
				{
					this.Agent = new Common.AgentComponent();
					InitAgent();

					//连接服务器
					Common.ConnectionServer conn = new Common.ConnectionServer(this.Agent);
					bool isStarted = conn.Connection();
					if (isStarted)
					{
						McsUtility.Models.LoginModel info = new McsUtility.Models.LoginModel
						{
							LoginName = Common.Data.LoginUserName,
							LoginPass = Common.Data.LoginPassWord
						};
						byte[] bytes = ProtocolHelper.WritePackage<McsUtility.Models.LoginModel>(ProtoType.MinerManagerLogin, info);
						this.Agent.AgentSend(bytes);

						this.FormReconnect.HandleFeedback(true);
					}
					else
					{
						Forms.Reconnect formReconnect = (Forms.Reconnect)obj;
						formReconnect.HandleFeedback(false);
					}
				};

				#endregion

				#region onCancel事件

				Action<object, EventArgs> onCancel = delegate (object obj, EventArgs args)
				{
					if (this.FormReconnect != null)
					{
						this.FormReconnect.Dispose();
						this.FormReconnect = null;
					}
				};

				#endregion

				if (this.FormReconnect == null)
				{
					this.FormReconnect = new Forms.Reconnect();
					this.FormReconnect.Owner = this;
					this.FormReconnect.OnHandle += new EventHandler<EventArgs>(onHandle);
				}

				if (!this.Agent.IsStarted && !this.FormReconnect.Visible)
				{
					this.FormReconnect.ShowDialog();
				}
			}
		}

		#endregion

		#region void RefreshStaffDisplay() 刷新客户经理的显示内容。

		private delegate void DelegateRefreshStaffDisplay();

		/// <summary>
		/// 刷新客户经理的显示内容。
		/// </summary>
		private void RefreshStaffDisplay()
		{
			if (this.InvokeRequired)
			{
				DelegateRefreshStaffDisplay d = new DelegateRefreshStaffDisplay(RefreshStaffDisplay);
				this.BeginInvoke(d);
			}
			else
			{
				string staffName = string.Empty;

				if (!string.IsNullOrWhiteSpace(Common.Data.Staff.Name))
					staffName += "客户经理：" + Common.Data.Staff.Name;

				if (!string.IsNullOrWhiteSpace(Common.Data.Staff.QQ1))
				{
					staffName += !string.IsNullOrWhiteSpace(staffName) ? " " : "";
					staffName += "QQ：" + Common.Data.Staff.QQ1;
				}

				if (!string.IsNullOrWhiteSpace(Common.Data.Staff.WeiXin1))
				{
					staffName += !string.IsNullOrWhiteSpace(staffName) ? " " : "";
					staffName += "微信：" + Common.Data.Staff.WeiXin1;
				}

				BottomStatus_Version.Text = (!string.IsNullOrWhiteSpace(staffName) ? staffName + " " : "") + Common.Utility.SoftName + " " + Common.Utility.Version;
			}
		}

		#endregion
	}
}
